library ieee;
use ieee.std_logic_1164.all;

package wr_pkg is

    function f_log2_size (A: natural) return natural;

    constant C_WRF_DATA   : std_logic_vector(1 downto 0) := "00";
    constant C_WRF_OOB    : std_logic_vector(1 downto 0) := "01";
    constant C_WRF_STATUS : std_logic_vector(1 downto 0) := "10";
    constant C_WRF_USER   : std_logic_vector(1 downto 0) := "11";

    constant C_WRF_OOB_TYPE_RX : std_logic_vector(3 downto 0) := "0000";
    constant C_WRF_OOB_TYPE_TX : std_logic_vector(3 downto 0) := "0001";

    constant C_WISHBONE_ADDRESS_WIDTH : integer := 32;
    constant C_WISHBONE_DATA_WIDTH    : integer := 32;

    subtype t_wishbone_address is
        std_logic_vector(C_WISHBONE_ADDRESS_WIDTH-1 downto 0);
    subtype t_wishbone_data is
        std_logic_vector(C_WISHBONE_DATA_WIDTH-1 downto 0);
    subtype t_wishbone_byte_select is
        std_logic_vector((C_WISHBONE_ADDRESS_WIDTH/8)-1 downto 0);
    subtype t_wishbone_cycle_type is
        std_logic_vector(2 downto 0);
    subtype t_wishbone_burst_type is
        std_logic_vector(1 downto 0);

    type t_wishbone_interface_mode is (CLASSIC, PIPELINED);
    type t_wishbone_address_granularity is (BYTE, WORD);

    type t_wishbone_master_out is record
        cyc : std_logic;
        stb : std_logic;
        adr : t_wishbone_address;
        sel : t_wishbone_byte_select;
        we  : std_logic;
        dat : t_wishbone_data;
    end record t_wishbone_master_out;

    subtype t_wishbone_slave_in is t_wishbone_master_out;

    type t_wishbone_slave_out is record
        ack   : std_logic;
        err   : std_logic;
        rty   : std_logic;
        stall : std_logic;
        int   : std_logic;
        dat   : t_wishbone_data;
    end record t_wishbone_slave_out;

    subtype t_wishbone_master_in is t_wishbone_slave_out;

    constant CC_DUMMY_ADDRESS : std_logic_vector(C_WISHBONE_ADDRESS_WIDTH-1 downto 0) :=
    (others => 'X');
    constant CC_DUMMY_DATA : std_logic_vector(C_WISHBONE_ADDRESS_WIDTH-1 downto 0) :=
    (others => 'X');
    constant CC_DUMMY_SEL : std_logic_vector(C_WISHBONE_DATA_WIDTH/8-1 downto 0) :=
    (others => 'X');
    constant CC_DUMMY_SLAVE_IN : t_wishbone_slave_in :=
    ('0', '0', cc_dummy_address, cc_dummy_sel, 'X', cc_dummy_data);
    constant CC_DUMMY_MASTER_OUT : t_wishbone_master_out := CC_DUMMY_SLAVE_IN;

    -- Dangerous! Will stall a bus.
    constant CC_DUMMY_SLAVE_OUT : t_wishbone_slave_out :=
    ('X', 'X', 'X', 'X', 'X', cc_dummy_data);
    constant CC_DUMMY_MASTER_IN : t_wishbone_master_in := CC_DUMMY_SLAVE_OUT;

    constant CC_UNUSED_MASTER_IN : t_wishbone_master_in :=
    ('1', '0', '0', '0', '0', cc_dummy_data);

    type t_wrf_mux_class is array (natural range <>) of std_logic_vector(7 downto 0);

    type t_wrf_status_reg is record
        is_hp       : std_logic;
        has_smac    : std_logic;
        has_crc     : std_logic;
        error       : std_logic;
        tag_me      : std_logic;
        match_class : std_logic_vector(7 downto 0);
    end record;

    type t_wrf_source_out is record
        adr : std_logic_vector(1 downto 0);
        dat : std_logic_vector(15 downto 0);
        cyc : std_logic;
        stb : std_logic;
        we  : std_logic;
        sel : std_logic_vector(1 downto 0);
    end record;

    type t_wrf_source_in is record
        ack   : std_logic;
        stall : std_logic;
        err   : std_logic;
        rty   : std_logic;
    end record;


    type t_wrf_oob is record
        valid: std_logic;
        oob_type : std_logic_vector(3 downto 0);
        ts_r     : std_logic_vector(27 downto 0);
        ts_f     : std_logic_vector(3 downto 0);
        frame_id : std_logic_vector(15 downto 0);
        port_id  : std_logic_vector(5 downto 0);
    end record;

    subtype t_wrf_sink_in is t_wrf_source_out;
    subtype t_wrf_sink_out is t_wrf_source_in;

    type t_wrf_source_in_array is array (natural range <>) of t_wrf_source_in;
    type t_wrf_source_out_array is array (natural range <>) of t_wrf_source_out;

    subtype t_wrf_sink_in_array is t_wrf_source_out_array;
    subtype t_wrf_sink_out_array is t_wrf_source_in_array;

    constant C_DUMMY_SRC_IN : t_wrf_source_in :=
        ('0', '0', '0', '0');
    constant C_DUMMY_SNK_IN : t_wrf_sink_in :=
        ("XX", "XXXXXXXXXXXXXXXX", '0', '0', '0', "XX");
		
    function f_marshall_wrf_status (stat  : t_wrf_status_reg) return std_logic_vector;
    function f_unmarshall_wrf_status(stat : std_logic_vector) return t_wrf_status_reg;
	 
end wr_pkg;

package body wr_pkg is

function f_log2_size (A : natural) return natural is
begin
    for I in 1 to 64 loop               -- Works for up to 64 bits
        if (2**I >= A) then
            return(I);
        end if;
    end loop;
    return(63);
end function f_log2_size;


function f_marshall_wrf_status(stat : t_wrf_status_reg)
    return std_logic_vector is
    variable tmp : std_logic_vector(15 downto 0);
    begin
        tmp(0)           := stat.is_hp;
        tmp(1)           := stat.error;
        tmp(2)           := stat.has_smac;
        tmp(3)           := stat.has_crc;
        tmp(4)           := '0';
        tmp(5)           := '0';
        tmp(6)           := '0';
        tmp(7)           := '0';
        tmp(15 downto 8) := stat.match_class;
    return tmp;
end function;

function f_unmarshall_wrf_status(stat : std_logic_vector) return t_wrf_status_reg is
    variable tmp : t_wrf_status_reg;
    begin
        tmp.is_hp       := stat(0);
        tmp.error       := stat(1);
        tmp.has_smac    := stat(2);
        tmp.has_crc     := stat(3);
        tmp.match_class := stat(15 downto 8);
    return tmp;
end function;

end wr_pkg;
